package com.xb.loan.usercenter.user.user.service.impl;


import com.xb.loan.log.exception.BizException;
import com.xb.loan.usercenter.service.user.ISessionService;
import com.xb.loan.usercenter.service.user.ITokenService;
import com.xb.loan.usercenter.service.user.IUserLoginService;
import com.xb.loan.usercenter.service.user.IUserService;
import com.xb.loan.usercenter.service.user.bean.LoginInfoVO;
import com.xb.loan.usercenter.service.user.bean.UserInfoVO;
import com.xb.loan.usercenter.service.user.bean.UserSessionIdBakVO;
import com.xb.loan.usercenter.service.user.exception.IUserServiceException;
import com.xb.loan.usercenter.user.util.PropertyConf;
import com.xb.loan.util.common.ObjectOperation;
import com.xb.loan.util.log.DefaultLoggerFacotry;
import com.xb.loan.util.log.LogFormatUtil;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

@Service("userLoginService")
public class UserLoginServiceImpl implements IUserLoginService, IUserServiceException {

    Logger logger = DefaultLoggerFacotry.getLogger(UserLoginServiceImpl.class);

    @Autowired
    IUserService userService;
    
    @Autowired
    ISessionService sessionService;
    
    @Autowired
	PropertyConf propertyConf;

    @Autowired
    ITokenService tokenService;


    public LoginInfoVO queryUserInfoByTotken(String token) throws BizException {
		UserInfoVO userInfoVO = userService.queryUserInfoByToken(token);

		if(userInfoVO == null){
			throw userInfoMissing;
		}
		LoginInfoVO loginInfoVO = createLoginInfoVO(userInfoVO);
		return loginInfoVO;
	}
    
	public LoginInfoVO createLoginInfoVO(UserInfoVO userInfoVO)throws BizException {
		
		LoginInfoVO loginInfoVO = ObjectOperation.convertByClasses(userInfoVO, LoginInfoVO.class);
		/*if(propertyConf.getExpiredTime() != null){
			loginInfoVO.setExpiredTime(propertyConf.getExpiredTime());
		}*/
    	Date curDate = new Date();
    	loginInfoVO.setLastAccessTime(curDate);
    	loginInfoVO.setLastLoginTime(curDate);
    	loginInfoVO.setToken(userInfoVO.getToken());
    	loginInfoVO.setSessionId(userInfoVO.getToken());


		return loginInfoVO;
	}
	
	public UserSessionIdBakVO createUserSessionIdBakVO(String userId, String sessionId)throws BizException {
		
		UserSessionIdBakVO userSessionIdBakVO = new UserSessionIdBakVO();
		userSessionIdBakVO.setUserId(userId);
		userSessionIdBakVO.setSessionId(sessionId);
		return userSessionIdBakVO;
	}
	
	/**
	 * 用两个Map来存储会话信息：分别是UserSessionIdBakVO和LoginInfoVO
	 * a)当用户正常登录时，两者都会存储用户登录信息，正常退出时都会清除。
	 * b)当用户非正常退出时，考虑到无法正常清除掉LoginInfoVO的Map里的用户信息， 因此增加UserSessionIdBakVO
	 * 用户登录时添加TOKEN生成
	 */
	@Override
	public LoginInfoVO loginUser(int userType, String loginName, String pwd) throws BizException{

		UserInfoVO userInfoVO = userService.queryUserInfoByUserType(userType, loginName);

		LoginInfoVO loginInfoVO = null;
		Date curDate = new Date();
		//如果登录用户不存在，则先进行注册再登录
		if(userInfoVO == null){
			loginInfoVO = userService.registerUser(30,"",loginName,pwd);
			//用户登录系统生成用户Token,参数为用户ID和用户手机号码
			String token = tokenService.createUserToken(Long.parseLong(userInfoVO.getUserId()),userInfoVO.getPhone());
			Date effDate = tokenService.getTokenDate(token);
			loginInfoVO.setLastAccessTime(curDate);
			loginInfoVO.setLastLoginTime(curDate);
			loginInfoVO.setToken(userInfoVO.getToken());
			loginInfoVO.setSessionId(userInfoVO.getToken());
		}else {
			if (!userInfoVO.getPwd().equals(pwd)) {
				throw loginPasswordError;
			}
			//用户登录系统生成用户Token,参数为用户ID和用户手机号码
			String token = tokenService.createUserToken(Long.parseLong(userInfoVO.getUserId()),userInfoVO.getPhone());
			Date effDate = tokenService.getTokenDate(token);
			//更新数据库最后一次登录时间
			userService.updateLastLoginTime(userInfoVO.getUserId(), curDate,token,effDate);
			userInfoVO.setToken(token);
			userInfoVO.setTokenEffectiveDate(effDate);
			//创建返回的用户登录信息
			loginInfoVO = createLoginInfoVO(userInfoVO);
		}

		//将登录信息数据写入redis缓存
		sessionService.insertUserInfoCacheOnly(loginInfoVO);
		//判断用户是否正常退出
		
		UserSessionIdBakVO userSessionIdBakVO = sessionService.queryUserSessionIdBakVO(loginInfoVO.getUserId());
		if(userSessionIdBakVO != null){
			
			if(!userSessionIdBakVO.getSessionId().equals(loginInfoVO.getSessionId())){
				
				//清除非正常退出的老的LoginInfoVO信息
				logger.info(LogFormatUtil.getFormatTemplate(new String[]{"module","userId","time"}),
						new Object[]{"Notice:UserLoginServiceImpl.loginUser clearUserInfoCache",userInfoVO.getUserId(),new Date()});

				//更新备份记录新的UserId和SessionId映射关系
				userSessionIdBakVO.setSessionId(loginInfoVO.getSessionId());
				sessionService.updateUserSessionIdBakVO(userSessionIdBakVO);

			}
		}else{
			
			//新增备份记录新的UserId和SessionId映射关系
			userSessionIdBakVO = createUserSessionIdBakVO(loginInfoVO.getUserId(),loginInfoVO.getSessionId());
			sessionService.insertUserSessionIdBakVO(userSessionIdBakVO);

		}
		return loginInfoVO;
	}

	public boolean loginOut(String sessionId) throws BizException {
		
		LoginInfoVO loginInfoVO = sessionService.queryUserInfoCacheOnly(sessionId);
		sessionService.clearUserInfoCache(sessionId);
		sessionService.clearUserSessionIdBakVO(loginInfoVO.getUserId());
		
//		boolean clearLoginFlag = sessionService.clearUserInfoCache(sessionId);
//		boolean clearBakFlag = sessionService.clearUserSessionIdBakVO(loginInfoVO.getUserId());
//		if(!clearLoginFlag){
//			logger.info(LogFormatUtil.getFormatTemplate(new String[]{"module","clearLoginFlag","sessionId"}),
//					new Object[]{"Notice:UserLoginServiceImpl.loginOut clearLoginFlag failure",clearLoginFlag,loginInfoVO.getSessionId()});
//			return false;
//		}
//		if(!clearBakFlag){
//			logger.info(LogFormatUtil.getFormatTemplate(new String[]{"module","clearBakFlag","sessionId"}),
//					new Object[]{"Notice:UserLoginServiceImpl.loginOut clearBakFlag failure",clearBakFlag,loginInfoVO.getSessionId()});
//			return true;
//		}
		return true;
    }
    
    public int updatePwd(String userId, String pwd) throws BizException {
    	
        return userService.updatePwd(userId,pwd);
    }
	
}
